#include "PikmenEnemy.h"

#include "setBehavior.h"
#include "Behavior/AllBehavior.h"
#include "Behavior/setSeek.h"

#include <ctime>
#include "AnimationPikmenEnemyDown.h"
#include "AnimationPikmenEnemyUp.h"
#include "AnimationPikmenEnemyRight.h"
#include "AnimationPikmenEnemyLeft.h"
#include "AnimationPikmenBall.h"
#include "CApp.h"

#include <math.h>
#include <stdlib.h>
#include <iostream>
#include <stdio.h>

#include <SDL/SDL_gfxPrimitives.h>

PikmenEnemy::PikmenEnemy(){
  timeRecover = 500;
  oldTimeRecover = 0;
  max_life = LIFE_ENEMY;
}

bool PikmenEnemy::OnInit(Character* target){
  return true;
}

/*
 * Inicializa al bicho
 */
bool PikmenEnemy::OnInit(vector<Character*>* ch,vector<Obstacle*>* ob,int posX, int posY,Character* target){
  
  // animaciones...
  animations.push_back(new AnimationPikmenEnemyUp());
  animations.push_back(new AnimationPikmenEnemyRight());
  animations.push_back(new AnimationPikmenEnemyDown());
  animations.push_back(new AnimationPikmenEnemyLeft());
  animations.push_back(new AnimationPikmenBall());
  currentAnimation = animations[0];
  _animation_oldtime = SDL_GetTicks();
  
  /* Posicionamos el personaje */
  k = new Kinematic();
  k->position[0] = posX;
  k->position[1] = posY;
  k->orientation = M_PI*((float) (random()%7))/7;
  k->max_velocity = 0.06;
  k->max_rotation = 0.004;
  this->width = 30;
  this->height =14;
  
//estado = WAITING;
  player = target;
  behaviors.push_back(new setSeek(this,target,ch,ob));
  behaviors.push_back(new Waiting(this,ch,ob));
  state = new WaitingPE(behaviors[1]);
  
  /* Asignamos la vida del Pikmen malo*/
  life = LIFE_ENEMY;
  
//cout << "Salio del OnInit de Pikmen.cpp" << endl;
  return true;
}

/*
 * Pinta al bicho
 */
void PikmenEnemy::OnRender(SDL_Surface* display){
    int fakeX, fakeY;
    int fakeW, fakeH;

    if(this->estaFrito) return;

    /// Primero una sombra
    fakeW = width-k->position[2]*.005;
    fakeH = height-k->position[2]*.005;
    filledEllipseRGBA(display,
        fixX(this->k->position[0]),fixY(this->k->position[1]),
        fakeW, fakeH,
        0, 0, 0, 128
        );

    /// Puntero de direccion
    fakeX = k->position[0] + fakeW*cos(k->orientation-M_PI/2);
    fakeY = k->position[1] + fakeH*-sin(k->orientation-M_PI/2);
    filledEllipseRGBA(display,
        fixX(fakeX),fixY(fakeY),
        width/4, height/3,
        0, 60, 0, 200
        );

    /// Sprite de la animacion
    fakeX = k->position[0]-currentAnimation->getWidth()/2;
    fakeY = k->position[1]-currentAnimation->getHeight()+5-k->position[2]*.08;

    if( length(k->velocity) < 0.000001 ){
        CSurface::OnDraw(display, currentAnimation->getFrame(),
            fixX(fakeX),fixY(fakeY),
            0, 0,
            currentAnimation->getWidth(), currentAnimation->getHeight()
            );
    } else {
        CSurface::OnDraw(display, currentAnimation->getFrame(),
            fixX(fakeX), fixY(fakeY),
            currentAnimation->getX(), currentAnimation->getY(),
            currentAnimation->getWidth(), currentAnimation->getHeight()
            );
    }

    // Un pixel de control, para saber donde esta el centro
    pixelRGBA(display,
        fixX(this->k->position[0]),
        fixY(this->k->position[1]),
        255, 0, 0, 128
        );
    Sint16 x = k->position[0] - 20, y =k->position[1] - 60;
    x = fixX(x);
    y = fixY(y);
    int lonRect = 40;
    const Sint16 vx[4] = {x,x,
      x+ ((float)life/LIFE_ENEMY)*lonRect,
      x+ ((float)life/LIFE_ENEMY)*lonRect};
    const Sint16 vy[4] = {y,y+5,y+5,y};

    if(life>0)
      filledPolygonColor(display,vx,vy,4,0xf41c1cff);

    rectangleColor(display,x,y,x+lonRect,y+5,0xffffffff);
}

/*
* Aplica comportamiento, actualiza la posicion
* y anima sprites (proximamente)
*/
void PikmenEnemy::OnLoop(long time){
  double _3pi4 = 3*M_PI/4;
  double _pi4 = M_PI/4;
  Uint32 current_time;
  Animation *aux;
  Steering* steering = NULL;
  Kinematic *myK = this->getKinematic(), *b = player->getKinematic();
  _flash_pikmen= this;
  State *saux = state->procces(life,myK,b,theApp.enemyCercaB(myK),behaviors,max_life);
  if (saux){
    delete(state);
    state= saux;
  }
  steering = state->getSteering();
/*
  switch(estado){
    case WAITING:
//    cout << " Waiting " << endl;
      steering = behaviors[1]->getSteering();
      float aux[3];
      restarVectores(myK->position,b->position,aux);
      if (length(aux) <=180)
        estado = SEEK_PLAYER;
      break;
    case SEEK_PLAYER:
//    cout << " Seek player " << endl;
      steering = behaviors[0]->getSteering();
      restarVectores(myK->position,b->position,aux);
      if (abs(aux[0]) >250 || abs(aux[1]) >250)
        estado = WAITING;
      if (abs(aux[0]) < 50 && abs(aux[1]) < 50){
        estado = ATACAR;
        if (old_time){
//        cout << "Ataque en Seek " << endl;
          player->atacado(this);
          old_time = SDL_GetTicks();
        }
//      cout << " old_time " <<old_time << endl;
      }
      break;
    case ATACAR:
//    cout << " Atacar " << endl;
      steering = behaviors[0]->getSteering();
      restarVectores(myK->position,b->position,aux);
      if (abs(aux[0]) >50 || abs(aux[1]) >50)
        estado = SEEK_PLAYER;
      else{
        if (SDL_GetTicks()- old_time > 1550){
          player->atacado(this);
          old_time = SDL_GetTicks();
        }
      }
      break;
    default:
      cout << "Default " << endl;
      break;
  }
*/
  delete(myK); delete(b);

  // Verificamos coliciones (collides)
  float *current = (float *) malloc(sizeof(float)*3);
  float *I = (float *) malloc(sizeof(float)*3);
  float *N = (float *) malloc(sizeof(float)*3);
  if(theApp.getCollision(this, &current, &I, &N)){
    // Acomodamos la posicion del jugador inmediatamente
    k->position[0] = current[0];
    k->position[1] = current[1];

    if(N[0]) k->velocity[0] =
      ((k->velocity[0]<0)?1:-1) * k->max_velocity;
    if(N[1]) k->velocity[1] =
      ((k->velocity[1]<0)?1:-1) * k->max_velocity;
  }
  free(current);
  free(I);
  free(N);

  // Agregamos un efecto constante... gravedad
  steering->linear[2] += -0.008;
  update(steering, time);
  delete steering;
  // Hay que animarlo
  // Seleccionamos la animacion adecuada...
  current_time = SDL_GetTicks();
  aux = currentAnimation;
  if(_animation_oldtime+250 < current_time){
    if(k->orientation>=_3pi4 || k->orientation<= -_3pi4){
        currentAnimation = animations[0];
    } else if(k->orientation<=_3pi4 && k->orientation>=_pi4){
        currentAnimation = animations[1];
    } else if(k->orientation<=_pi4 && k->orientation>=-_pi4){
        currentAnimation = animations[2];
    } else {
        currentAnimation = animations[3];
    }
    if(aux != currentAnimation)
      _animation_oldtime = SDL_GetTicks();
  }
  currentAnimation->OnAnimate();

  // El enemigo recupera energia gradualmente
  long currentRecover = SDL_GetTicks();
  if(currentRecover-oldTimeRecover>=timeRecover){
    oldTimeRecover = currentRecover;
//  this->addLife(2);
  }
}
